package Model.SurroundModel;

import Model.check_inside_util.CheckSurround;
import Model.check_inside_util.ParamChangeUtil;
import Model.extract_feature_point_test_data.TestData;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Target {
    public int num; //目标的编号
    public double x; //目标的x坐标
    public double y; //目标的y坐标
    public double d; //目标到目标中心距离的估计值
    public double d_v; //目标到目标中心的实际值
    public double d0; //虚拟目标的距离中心的距离
    public ArrayList<Target> targets = new ArrayList<Target>(); //目标群
    public ArrayList<Target> virtualTargets = new ArrayList<>(); //虚拟目标群
    public static double x0; //目标中心x坐标
    public static double y0; //目标中心y坐标
    public static double vx0; //虚拟目标中心x坐标
    public static double vy0; //虚拟目标中心y坐标
    public double range; //目标距离最近目标的位置
    public double xx; //目标的x坐标
    public double yy; //目标的y坐标 xx,yy用于计算p（t）p(t)是目标中心的位置
    public ArrayList<Double> VirtualDis = new ArrayList<Double>();  // 存放虚拟目标与中心距离的队列
    public ArrayList<Target> targetindex = new ArrayList<>(); //存放符合条件的目标
    public double Rx; //虚拟目标x方向的导数
    public double Ry; //虚拟目标y方向的导数

    public void clear() {
        x0 = 0;
        y0 = 0;
    }

    //默认构造函数
    public Target() {
    }

    //初始化目标群
    public Target(ArrayList<Target> targets) {
        this.targets = targets;
    }

    //初始化某一目标坐标
    public Target(int num, double x, double y) {
        this.num = num;
        this.x = x;
        this.y = y;
    }

    //计算欧氏距离
    public static double distance(double x1, double y1, double x2, double y2) {
        return Math.sqrt(Math.pow((x1 - x2), 2) + Math.pow((y1 - y2), 2));
    }

    public  void setPosition(double t) {
        if (t <= 0.5) {
            t *= 10;
            targets.get(0).x = t + 5;
            targets.get(0).y = t + 5 - Math.sin(t);
            targets.get(1).x = t + 3;
            targets.get(1).y = t + 5 + Math.sin(t);
            targets.get(2).x = t + 5;
            targets.get(2).y = t + 3 - Math.sin(t);
            targets.get(3).x = t + 7;
            targets.get(3).y = t + 5 + Math.sin(t);
        } else
            return;
    }

    //计算目标中心位置坐标
    public  void setCenter() {
        double xi = 0;
        double yi = 0;

        for (int i = 0; i < targets.size(); i++) {
            xi += targets.get(i).x;
            yi += targets.get(i).y;
        }

        x0 = xi / targets.size();
        y0 = yi / targets.size();
        //System.out.println("x0:" + x0 + "  y0:" + y0);
    }

    //计算某一时刻目标距离目标平均中心的最大值
    public  void setd(double t,Ship Ship,Target Target) {
        for (int i = 0; i < 100; i++) {
            Ship.setφ(0.0001);
            Ship.setP(0.0001,Target);
        }
        for (Target target : Target.targets) {
            target.d = distance(target.x, target.y, target.xx, target.yy);
            //System.out.println("num:" + target.num + " di：" + target.d);
        }
    }

    //计算某一时刻目标距离目标平均中心的最大值
    public  void setd(double t,ShipSampling Ship,Target Target) {
        for (int i = 0; i < 100; i++) {
            Ship.setφ(0.0001);
            Ship.setP(0.0001,Target);
        }
        for (Target target : Target.targets) {
            target.d = distance(target.x, target.y, target.xx, target.yy);
            //System.out.println("num:" + target.num + " di：" + target.d);
        }
    }

    //计算目标距离目标平均中心的最大值
    public double dmax(Target target) {
        double max = 0;
        if(this.num == 1){
            max = Math.max(this.d,target.targets.get(this.num).d);
        }
        else if (this.num == 2){
            max = Math.max(Math.max(this.d,target.targets.get(this.num-2).d),Math.max(this.d,target.targets.get(this.num).d));
        }
        else if (this.num == 3){
            max = Math.max(Math.max(this.d,target.targets.get(this.num-2).d),Math.max(this.d,target.targets.get(this.num).d));
        }
        else {
            max = Math.max(this.d,target.targets.get(this.num-2).d);
        }
        return max;
    }

    //静止目标初始化目标位置
    public  void initCircularPosition() {
        targets.clear();
        targets.add(new Target(1, 0, 5));
        targets.add(new Target(2, 2, 0));
        targets.add(new Target(3, 0, -5));
        targets.add(new Target(4, -2, 0));
    }

    //目标编队初始化目标位置
    public  void initShapePosition() {
        targets.clear();
        targets.add(new Target(1, -3, 7));
        targets.add(new Target(2, 1, 2));
        targets.add(new Target(4, 7, 2));
        targets.add(new Target(3, 5, 4));
    }
    //通过采样虚拟化静态目标坐标
    public  void initStaticVirtualTargets(Target Target) throws IOException, IOException {
        NewSampling sampling = new NewSampling();
        sampling.calPoints = TestData.GetPentagramShips();
//        sampling.calPoints = TestData.GetCircleAndTriangleShips();
//        sampling.calPoints = TestData.GetRectangleShips();
        sampling.Sampling(20,sampling.calPoints.size());

        this.virtualTargets = sampling.targets;
        //先将虚拟目标的中心与实际目标中心重合
        double x_tmp=0;
        double y_tmp=0;
        double max_tmp = 0;
        double max = 0;
        for (Target t : virtualTargets){
            x_tmp+=t.x;
            y_tmp+=t.y;
        }
        for (Target t : virtualTargets){
            t.x = t.x - x_tmp/virtualTargets.size();
            t.y = t.y - y_tmp/virtualTargets.size();
            t.d0 = distance(t.x,t.y,0,0);
            if (t.d0>max_tmp) max_tmp=t.d0;
        }
        //再对虚拟目标进行比例缩放，使其尽可能接近实际目标
        for (Target target : Target.targets) {
            target.d = distance(target.x, target.y, Target.x0, Target.y0);
            if (target.d>max) max = target.d;
        }
        int mut = (int)(max_tmp/max);
        // System.out.println("mut="+mut);
        for (Target t : virtualTargets){
            t.x = t.x/mut +Target.x0;
            t.y = t.y/mut +Target.y0;
        }
         System.out.println("通过采样虚拟化静态目标坐标:");
        for (Target t : virtualTargets){
            System.out.println(t);
        }
    }
    //控制虚拟目标
    public void ControlVirtualTargets(double tt , Target target) {
        double x_tmp=0;
        double y_tmp=0;
        double ravg_dx = 0 ; // 用来存一定时间间隔的目标中心变化值
        double ravg_dy = 0 ;
        double r_x =0;
        double r_y =0;

        //计算目标中心的变化
        r_x = Target.x0;
        r_y = Target.y0;
        target.setCenter();
        ravg_dx = Target.x0 - r_x;
        ravg_dy = Target.y0 - r_y;
        // System.out.println("Target_x0"+Target.x0);
        for (Target targetT : virtualTargets){
            x_tmp+=targetT.x;
            y_tmp+=targetT.y;
        }
        vx0 = x_tmp/virtualTargets.size();
        vy0 = y_tmp/virtualTargets.size();
        //System.out.println("virtual_x0"+vx0);
        //存储虚拟目标距离中心的长度
        VirtualDis.clear();
        for (int j = 0; j < virtualTargets.size(); j++) {
            Double distance = Target.distance(virtualTargets.get(j).x, virtualTargets.get(j).y, Target.vx0, Target.vy0);
            VirtualDis.add(distance);
        }
        Collections.sort(VirtualDis);
        targetindex.clear();
        for (Target t : targets){
            t.d_v = distance(t.x,t.y,Target.x0,Target.y0);
            if (t.d_v > VirtualDis.get(0)){
                targetindex.add(t);
            }
        }
        Collections.sort(targets, new Comparator<Target>() {
            @Override
            public int compare(Target o1, Target o2) {
                double a = o1.d_v - o2.d_v;
                if (a > 0) return -1;
                else if (a == 0) return 0;
                else return 1;
            }
        });
        for (Target vtarget : virtualTargets) {
            if (Math.abs(Target.x0-Target.vx0)<0.01) {
                vtarget.x = vtarget.x + CheckSurround.Surround(ParamChangeUtil.TargetsToPoints(virtualTargets), ParamChangeUtil.TargetsToPoints(targets))*(ravg_dx) ;
                vtarget.y = vtarget.y + CheckSurround.Surround(ParamChangeUtil.TargetsToPoints(virtualTargets), ParamChangeUtil.TargetsToPoints(targets))*(ravg_dy) ;
                //vtarget.x = vtarget.x + ravg_dx ;
                //vtarget.y = vtarget.y + ravg_dy ;
                System.out.println("______________________________________________");
            }else {
                vtarget.x = vtarget.x + ravg_dx +CheckSurround.Surround(ParamChangeUtil.TargetsToPoints(virtualTargets), ParamChangeUtil.TargetsToPoints(targets))*( 20 * Math.signum(Target.x0 - vx0) * tt);
                vtarget.y = vtarget.y + ravg_dy +CheckSurround.Surround(ParamChangeUtil.TargetsToPoints(virtualTargets), ParamChangeUtil.TargetsToPoints(targets))*( 20 * Math.signum(Target.y0 - vy0) * tt);
                //vtarget.x = vtarget.x + ravg_dx + 20 * Math.signum(Target.x0 - vx0) * tt;
               // vtarget.y = vtarget.y + ravg_dy + 20 * Math.signum(Target.y0 - vy0) * tt;
                System.out.println("1111111111111111111111111111111111111");
           }
        }
        if (!targetindex.isEmpty()) {
            for (Target vtarget : virtualTargets) {
                Rx = 2* Math.signum(targetindex.get(0).d_v - VirtualDis.get(0)) * vtarget.x ;
                Ry = 2* Math.signum(targetindex.get(0).d_v - VirtualDis.get(0)) * vtarget.y ;
                vtarget.x = vtarget.x + CheckSurround.Surround(ParamChangeUtil.TargetsToPoints(virtualTargets), ParamChangeUtil.TargetsToPoints(targets)) * Rx * tt ;
                vtarget.y = vtarget.y + CheckSurround.Surround(ParamChangeUtil.TargetsToPoints(virtualTargets), ParamChangeUtil.TargetsToPoints(targets)) * Ry * tt ;
//                Rx = 2* Math.signum(targetindex.get(0).d_v - VirtualDis.get(0)) * vtarget.x ;
//                Ry = 2* Math.signum(targetindex.get(0).d_v - VirtualDis.get(0)) * vtarget.y ;
//                vtarget.x = vtarget.x + Rx * tt ;
//                vtarget.y = vtarget.y + Ry * tt ;
            }
            //System.out.println(Math.signum(targetindex.get(0).d_v - VirtualDis.get(0)));
            //System.out.println(Math.signum(Math.signum((int)Target.x0-vx0)));
        }
    }
    public static void main(String args[]) throws IOException {
        Target target  = new Target();
        target.initCircularPosition();
        target.setCenter();
        target.initStaticVirtualTargets(target);
    }
}
